package com.roncoo.eshop.inventory.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.roncoo.eshop.inventory.model.ProductInventory;
import com.roncoo.eshop.inventory.request.ProductInventoryCacheRefreshRequest;
import com.roncoo.eshop.inventory.request.ProductInventoryDBUpdateRequest;
import com.roncoo.eshop.inventory.request.Request;
import com.roncoo.eshop.inventory.service.ProductInventoryService;
import com.roncoo.eshop.inventory.service.RequestAsyncProcessService;
import com.roncoo.eshop.inventory.vo.ServiceCoreVO;

import lombok.extern.slf4j.Slf4j;

/**
 * Copyright: Copyright (c) 2019 Hu-Cheng
 * 
 * @ClassName: ProductInventoryController.java
 * @Description: 商品库存控制层
 *
 * @version: v1.0.0
 * @author: hucheng
 * @date: 2019年9月19日 下午2:34:32
 *
 */
@Slf4j
@RestController
public class ProductInventoryController {

	@Autowired
	private ProductInventoryService productInventoryService;

	@Autowired
	private RequestAsyncProcessService requestAsyncProcessService;

	/**
	 * 更新商品库存
	 * 
	 * @param productInventory
	 * @return Response
	 */
	@RequestMapping("updateProductInventory")
	public ServiceCoreVO updateProductInventory(ProductInventory productInventory) {
		ServiceCoreVO response = null;
		try {
			log.info("更新库存开始 >>>>>> 商品id：" + productInventory.getProductId() + "，库存："
					+ productInventory.getInventoryCnt());
			Request request = new ProductInventoryDBUpdateRequest(productInventory, productInventoryService);
			requestAsyncProcessService.process(request);

			response = new ServiceCoreVO(ServiceCoreVO.SUCCESS);
		} catch (Exception e) {
			e.printStackTrace();
			response = new ServiceCoreVO(ServiceCoreVO.FAILURE);
		}

		return response;
	}

	/**
	 * 获取商品库存
	 * 
	 * @param productId
	 * @return ProductInventory
	 */
	@SuppressWarnings("unused")
	@RequestMapping("getProductInventory")
	public ProductInventory getProductInventory(Integer productId) {
		ProductInventory productInventory = null;

		try {
			log.info("读取缓存 >>>>>> 商品id：" + productId);
			Request request = new ProductInventoryCacheRefreshRequest(productId, productInventoryService, false);

			requestAsyncProcessService.process(request);

			// 将请求丢给异步service去处理之后，就需要while(true)一会，在这里会挂一会
			// 去尝试等待前面的商品库存更新完操作，同时缓存刷新的问题，将最新的数据刷新到redis中
			long startTime = System.currentTimeMillis();
			long endTime = 0L;
			long waitTime = 0L;

			while (true) {
				if (waitTime > 200) {
					break;
				}

				log.info("读取缓存 >>>>>> 第一次从缓存中读取库存，商品id：" + productId);
				// 去尝试第一次读取redis缓存中的库存数据
				productInventory = productInventoryService.getProductInventoryCache(productId);
				log.info("读取缓存 >>>>>> 缓存中是否存在库存，商品：" + JSONObject.toJSONString(productInventory));
				// 如果读取到了结果就直接返回
				if (productInventory != null) {
					return productInventory;
				}

				// 如果没有获取到结果，就等待一会
				Thread.sleep(20);
				endTime = System.currentTimeMillis();
				waitTime = endTime - startTime;
			}

			log.info("读取缓存 >>>>>> 缓存中没有数据，尝试从数据库中读取数据，商品id：" + productId);
			// 直接尝试从数据库中读取数据
			productInventory = productInventoryService.findProductInventory(productId);
			log.info("读取缓存 >>>>>> 从数据中读取数据商品id：" + productInventory.getProductId() + "，库存："
					+ productInventory.getInventoryCnt());
			if (productInventory != null) {
				log.info("更新缓存 >>>>>> 从数据中读取到库存后，再次将库存更新到缓存中，商品id：" + productId);
				// 从数据中取到数据后，顺便将缓存刷新的redis
				// 这里是第一次刷新缓存，由于flag 标识是false，所以不会不会去刷新缓存操作不会进入队列中去
				// 这时候需要加上强制刷新，当第一次从数据库中获取缓存的时候，必须强制刷新缓存到redis中去
				request = new ProductInventoryCacheRefreshRequest(productId, productInventoryService, true);
				request.process();

				return productInventory;
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return productInventory;
	}

}
